﻿using System;
using System.Linq;
using System.Collections.ObjectModel;

namespace Patterns.FactoryMethod {

    public static class AppliedExample {

        public static void Run() {
            Document[] documents = {
                new Resume(),
                new Report()};

            // Display document pages
            Array.ForEach(documents, document => {
                Console.WriteLine("\n" + document.GetType().Name + "--");
                foreach (Page page in document.Pages)
                    Console.WriteLine(" " + page.GetType().Name);
            });
        }
    }

    // "Product"
    abstract class Page { }

    // "ConcreteProduct"
    class SkillsPage : Page { }

    // "ConcreteProduct"
    class EducationPage : Page { }

    // "ConcreteProduct"
    class ExperiencePage : Page { }

    // "ConcreteProduct"
    class IntroductionPage : Page { }

    // "ConcreteProduct"
    class ResultsPage : Page { }

    // "ConcreteProduct"
    class ConclusionPage : Page { }

    // "ConcreteProduct"
    class SummaryPage : Page { }

    // "ConcreteProduct"
    class BibliographyPage : Page { }

    // "Creator"
    abstract class Document {
        public Collection<Page> Pages { get; private set; }

        // Constructor calls abstract Factory method
        public Document() {
            this.CreatePages();
            Pages = new Collection<Page>();
        }

        // Factory Method
        public abstract void CreatePages();
    }

    // "ConcreteCreator"
    class Resume : Document {
        // Factory Method implementation
        public override void CreatePages() {
            Pages.Add(new SkillsPage());
            Pages.Add(new EducationPage());
            Pages.Add(new ExperiencePage());
        }
    }

    // "ConcreteCreator"
    class Report : Document {
        // Factory Method implementation
        public override void CreatePages() {
            Pages.Add(new IntroductionPage());
            Pages.Add(new ResultsPage());
            Pages.Add(new ConclusionPage());
            Pages.Add(new SummaryPage());
            Pages.Add(new BibliographyPage());
        }
    }
}
